<?php
/**
 * Created by PhpStorm.
 * User: qch
 * Date: 2015/6/3
 * Time: 10:06
 */

namespace J\Util;
use J\Behavior;
use J\Message;


/**
 * 验证类
 */
class Validator extends Behavior
{
    // 验证函数不可执行
    const ERR_CLOSURE = -1;
    // 验证方法名称错误
    const ERR_METHOD  = -2;

    /**
     * @var mixed  验证参数
     */
    protected $arguments = null;

    public function __construct($name, $arguments = null)
    {
        //\Closure::
        $this->name = ucfirst($name);
        $this->arguments = $arguments;
    }

    /**
     * Validate that an attribute is a valid date.
     *
     * @param  mixed $value
     * @return bool
     * @internal param array $attribute
     */
    protected static function validateDate($value)
    {
        if ($value instanceof \DateTime) return true;

        if (strtotime($value) === false) return false;

        $date = date_parse($value);

        return checkdate($date['month'], $date['day'], $date['year']);
    }

    /**
     * Validate that an attribute is a valid IP.
     *
     * @param  mixed $value
     * @return bool
     * @internal param array $attribute
     */
    protected static function validateIp($value)
    {
        return filter_var($value, FILTER_VALIDATE_IP) !== false;
    }

    protected static function validateEqual($value, $attribute)
    {
        return $value === $attribute;
    }

    protected static function validateFunc($value, $attribute)
    {
        $function = array_shift($attribute);
        array_unshift($attribute, $value);

        if (is_callable($function)) {
            return call_user_func_array($function, $attribute);
        }

        return null;
    }

    /**
     * Validate that an attribute is a valid e-mail address.
     *
     * @param  mixed $value
     * @return bool
     * @internal param array $attribute
     */
    protected static function validateEmail($value)
    {
        return filter_var($value, FILTER_VALIDATE_EMAIL) !== false;
    }

    /**
     * Validate that an attribute is a valid URL.
     *
     * @param  mixed $value
     * @return bool
     * @param bool $attribute check active
     */
    protected static function validateUrl($value, $attribute = null)
    {
        if($attribute) {
            $url = str_replace(array('http://', 'https://', 'ftp://'), '', strtolower($value));
            return checkdnsrr($url, 'A');
        }
        return filter_var($value, FILTER_VALIDATE_URL) !== false;
    }

    /**
     * Validate that an attribute contains only alphabetic characters.
     *
     * @param  mixed $value
     * @return bool
     * @internal param array $attribute
     */
    protected static function validateAlpha($value)
    {
        return preg_match('/^[\pL\pM]+$/u', $value);
    }

    /**
     * Validate that an attribute contains only alphabetic characters.
     *
     * @param  mixed $value
     * @return bool
     * @param array $attribute
     */
    protected static function validateRange($value, $attribute)
    {
        $v = (int)$value;
        $min = 0;
        $max = PHP_INT_MAX;
        extract($attribute);

        return $v >= $min and $v <= $max;
    }

    /**
     * Validate that an attribute contains only alpha-numeric characters.
     *
     * @param  mixed $value
     * @return bool
     * @internal param array $attribute
     */
    protected static function validateAlphaNum($value)
    {
        return preg_match('/^[\pL\pM\pN]+$/u', $value);
    }

    /**
     * Validate that an attribute contains only alpha-numeric characters, dashes, and underscores.
     *
     * @param  mixed $value
     * @return bool
     * @internal param array $attribute
     */
    protected static function validateAlphaDash($value)
    {
        return preg_match('/^[\pL\pM\pN_-]+$/u', $value);
    }

    /**
     * Validate that an attribute passes a regular expression check.
     *
     * @param  string $attribute
     * @param  mixed $value
     * @return bool
     */
    protected static function validateRegex($value, $attribute)
    {
        return preg_match($attribute, $value);
    }

    /**
     * Validate that an attribute matches a date format.
     *
     * @param  array|string $attribute
     * @param  mixed $value
     * @return bool
     */
    protected static function validateDateFormat($value, $attribute = [])
    {
        $parsed = date_parse_from_format($attribute, $value);

        return ($parsed['error_count'] === 0 && $parsed['warning_count'] === 0);
    }

    /**
     * 执行行为 run方法是Behavior唯一的接口
     *
     * @param mixed $params  验证方法
     * @param array $context 错误信息
     *
     * @return bool 返回true继续
     */
    public function run(&$params = null, &$context = [])
    {
        $method = 'validate'.$this->name;

        if (method_exists($this,$method)) {
            $r = ((null !== $this->arguments) ?
                static::$method($params, $this->arguments) : static::$method($params));

            if ($r === false) return false;

            if ($r === null) {
                $context[] = [$this->name, static::ERR_CLOSURE];
                app()->error(Message::VALIDATOR_RUN_ERROR, ['name' => $this->name]);
                return null;
            }

            return true;
        } else {
            $context[] = [$this->name, static::ERR_METHOD];
            app()->error(Message::VALIDATOR_NOT_FIND, ['name' => $this->name]);
            return null;
        }
    }
}